package com.chenfan.common.extension.context;


import org.apache.commons.lang3.StringUtils;

import java.util.Objects;
import java.util.Optional;

/**
 * 链路上下文Holder
 *
 * @author wulg
 * @date 2022-04-26
 **/
public class TraceContextHolder {

    private static ThreadLocal<TraceContext> threadLocal = ThreadLocal.withInitial(() -> new TraceContext(4));

    public static TraceContext getCurrentContext() {
        return threadLocal.get();
    }

    public static void setContext(TraceContext context) {
        TraceContext currentContext = getCurrentContext();
        if(Objects.nonNull(context)) {
            context.copy(currentContext);
        }
    }

    public static <T> Optional<T> getOptional(String key) {
        return Optional.ofNullable(get(key));
    }

    public static <T> T get(String key) {
        TraceContext context = getCurrentContext();
        if(Objects.isNull(context)) {
            return null;
        }
        Object value = context.get(key);
        if(Objects.isNull(value)) {
            return null;
        }
        return (T)value;
    }

    public static boolean contains(String key) {
        return getOptional(key).isPresent();
    }

    public static <T> void put(String key, T value) {
        TraceContext context = getCurrentContext();
        if(Objects.nonNull(context)) {
            context.add(key, value);
        }
    }

    public static <T> void putActionName(String actionName) {
        TraceContext context = getCurrentContext();
        if(Objects.nonNull(context)) {
            context.add(TraceContext.ACTION_NAME, actionName);
        }
    }

    public static <T> void putSceneEntry(TraceContext.SceneEntry sceneEntry) {
        TraceContext context = getCurrentContext();
        if(Objects.nonNull(context)) {
            context.add(TraceContext.SCENE_ENTRY, sceneEntry.name());
        }
    }

    public static <T> boolean isFormJob() {
        String sceneEntry = get(TraceContext.SCENE_ENTRY);
        return StringUtils.equals(sceneEntry, TraceContext.SceneEntry.JOB.name());
    }

    public static void clear() {
        TraceContext context = getCurrentContext();
        if(Objects.nonNull(context)) {
            context.clear();
        }
        threadLocal.remove();
    }
}
